package com.csdj.middleware;

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.Serializable;
import java.time.Duration;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;

public class RedisService {

    @Resource(name = "jsonRedisTemplate")
    private RedisTemplate<String,Object> redisTemplate;

    //分布试锁的键值
    private final String LOCK_KEY = "redis_lock";
    //锁的超时时间
    private final Duration LOCK_TIME = Duration.ofMinutes(10);

    public RedisService() {
    }

    public RedisService(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }


    public String getString(String key){
        Object obj = redisTemplate.opsForValue().get(key);
        if(obj != null)return obj.toString();
        return null;
    }

    public void setString(String key,String value){
        redisTemplate.opsForValue().set(key,value);
    }

    public void setString(String key,String value,int second){
        redisTemplate.opsForValue().set(key,value,Duration.ofSeconds(second));
    }

    public <T extends Serializable> T getObject(String key){
        Object obj = redisTemplate.opsForValue().get(key);
        return (T) obj;
    }

    public void setObject(String key, Object object){
        redisTemplate.opsForValue().set(key,object);
    }

    public void setHash(String key ,String filed,String value){
        redisTemplate.opsForHash().put(key,filed,value);
    }

    public String getHashStr(String key , String filed){
        Object obj = redisTemplate.opsForHash().get(key,filed);
        if(obj != null)return obj.toString();
        return null;
    }

    /**
     * 加锁
     * @param id
     * @return
     */
    public boolean lock(int id) {
        final long start = System.currentTimeMillis();
        while(System.currentTimeMillis() - start < 1000*10){
            if(redisTemplate.opsForValue().setIfAbsent(LOCK_KEY,id,LOCK_TIME)){
                return true;
            }
            try {
                TimeUnit.MICROSECONDS.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
                return false;
            }
        }
        return false;//超时
    }

    /**
     * 解锁
     * @param id
     * @return
     */
    public boolean unlock(int id){
        String script = "if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end";
        final DefaultRedisScript<Long> longDefaultRedisScript = new DefaultRedisScript<>(script, Long.class);
        final Long res = redisTemplate.execute(longDefaultRedisScript, Arrays.asList(LOCK_KEY), id);
        return res>0;

    }
}
